import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
import { BankService } from "src/modules/bank/bank.service";
import { ClientService } from "src/modules/client/client.service";
import { DeliveryService } from "src/modules/delivery/delivery.service";
import { OrderService } from "src/modules/order/order.service";
import { QualityService } from "src/modules/quality/quality.service";
import { StatisticService } from "src/modules/statistics/statistic.service";
import { TypeService } from "src/modules/type/type.service";
import { UserService } from "src/modules/user/user.service";
import { IS_PUBLIC_KEY } from "../decorators/public.decorator";
import { JwtPayload } from "../interfaces/jwt.interface";

@Injectable()
export class CompanyGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    private readonly bankService: BankService,
    private readonly clientService: ClientService,
    private readonly deliveryService: DeliveryService,
    private readonly orderService: OrderService,
    private readonly qualityService: QualityService,
    private readonly statisticService: StatisticService,
    private readonly typeService: TypeService,
    private readonly usersService: UserService
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);
    // 如果是公开的，那么根本无所谓用户所属公司
    if (isPublic) {
      return true;
    }
    const request = context.switchToHttp().getRequest();
    // 有关Auth方面的内容，不会涉及到影响公司的任何信息。
    if ((request.route.path as string).startsWith("/auth")) {
      return true;
    }
    const user: JwtPayload = request.user;
    // 如果当前用户是管理者，那么它拥有一切权限。
    if (user.aud === "admin") return true;
    const controllerName = context.getClass().name;
    const id: string = request.params.id;
    // 如果不涉及id，说明本次操作只允许操作当前用户所在的公司的内容
    if (!id) {
      return true;
    }
    // 如果涉及id，那么就需要保证这次操作的对象是当前用户所在公司拥有的对象，而不是其它公司的对象
    const controllerMap = [
      { controller: "BankController", service: this.bankService },
      { controller: "ClientController", service: this.clientService },
      { controller: "DeliveryController", service: this.deliveryService },
      { controller: "OrderController", service: this.orderService },
      { controller: "QualityController", service: this.qualityService },
      { controller: "StatisticController", service: this.statisticService },
      { controller: "TypeController", service: this.typeService },
      { controller: "UserController", service: this.usersService },
      { controller: "DeliverOrderController", service: this.deliveryService },
    ];
    const item = await controllerMap
      .find((item) => item.controller === controllerName)
      ?.service.findOneWithCompany(id);
    if (item) {
      return item.company?.id === user.company;
    }
    return true;
  }
}
